package com.blm.service.impl;

import com.blm.common.constants.ExceptionConstant;
import com.blm.dto.AuditDTO;
import com.blm.dto.StoreCategoryDTO;
import com.blm.entity.*;
import com.blm.exception.CommonException;
import com.blm.exception.NotFoundException;
import com.blm.repository.*;
import com.blm.service.AdminService;
import com.blm.service.OrderService;
import com.blm.vo.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static com.blm.dto.AuditDTO.AuditStatus.APPROVED;
import static com.blm.dto.AuditDTO.AuditStatus.SUSPENDED;

/**
 * 管理员服务实现类
 */
@Service
public class AdminServiceImpl extends BaseService implements AdminService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private FoodRepository foodRepository;

    @Autowired
    private RiderRepository riderRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private OrderItemRepository orderItemRepository;

    @Autowired
    private ReviewRepository reviewRepository;

    @Autowired
    private StoreCategoryRepository storeCategoryRepository;

    @Autowired
    private OrderService orderService;

    /**
     * 获取用户列表
     */
    @Override
    public PageVO<UserVO> listUsers(User.UserRole role, Integer status, String keyword, int page, int size) {
        // 验证状态值是否合法
        if(status != null) {
            if(status != 0 && status != 1) {
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }
        }

        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);

        // 根据条件查询用户列表
        List<User> users = userRepository.findByConditions(role, status, keyword);

        // 获取PageHelper分页信息并自动关闭资源
        Page<User> pageInfo = (Page<User>) users;
        // 转换为VO列表
        List<UserVO> userVOs = entity2VO(users, UserVO.class);

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), userVOs);
    }

    /**
     * 更新用户状态
     */
    @Override
    @Transactional
    public void updateUserStatus(Long userId, AuditDTO dto) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException(ExceptionConstant.USER_NOT_FOUND));

        AuditDTO.AuditStatus status = dto.getStatus();
        // 验证状态值是否合法
        if(APPROVED.equals(status)){
            // 重复激活
            if(User.ACTIVE.equals(user.getStatus())){
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }

            user.setStatus(User.ACTIVE);
        }else if(SUSPENDED.equals(status)){
            // 重复禁用
            if(User.INACTIVE.equals(user.getStatus())){
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }

            user.setStatus(User.INACTIVE);
        }else {
            // 如果状态不合法，抛出异常
            throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
        }

        user.setUpdatedAt(LocalDateTime.now());
        userRepository.save(user);
    }

    /**
     * 获取商家店铺列表
     */
    @Override
    public PageVO<StoreVO> listStores(String status, String keyword, int page, int size) {
        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);

        // 验证状态值是否合法
        if(status != null) {
            try {
                Store.StoreStatus.valueOf(status);
            } catch (IllegalArgumentException e) {
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }
        }
        
        // 根据条件查询店铺列表
        List<Store> stores = storeRepository.findByStatusAndKeyword(status, keyword);
        
        // 获取PageHelper分页信息
        Page<Store> pageInfo = (Page<Store>) stores;
        // 转换为VO列表
        List<StoreVO> storeVOs = entity2VO(stores, StoreVO.class);

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), storeVOs);
    }

    /**
     * 审核店铺
     */
    @Override
    @Transactional
    public void auditStore(Long storeId, AuditDTO dto) {
        Store store = storeRepository.findById(storeId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.STORE_NOT_FOUND));

        // 验证状态值是否合法
        AuditDTO.AuditStatus status = dto.getStatus();
        if(APPROVED.equals(status)) {
            // 只有PENDING的店铺可以被审核通过(APPROVED)
//            if(!Store.StoreStatus.PENDING.equals(store.getStatus())) {
//                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
//            }

            // 默认为营业状态
            store.setStatus(Store.StoreStatus.CLOSED);
        } else if(SUSPENDED.equals(status)) {
            // 不能suspend 已经suspended的店铺
            if(Store.StoreStatus.SUSPENDED.equals(store.getStatus())) {
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }

            store.setStatus(Store.StoreStatus.SUSPENDED);
            store.setRejectReason(dto.getReason());
        } else {
            // 如果状态不合法，抛出异常
            throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
        }

        store.setUpdatedAt(LocalDateTime.now());
        storeRepository.setRejectReason(storeId, dto.getReason());
        storeRepository.save(store);
    }

    /**
     * 获取商品列表
     */
    @Override
    public PageVO<FoodVO> listFoods(Food.FoodStatus status, String keyword, Long storeId, int page, int size) {
        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);
        
        // 根据条件查询商品列表
        List<Food> foods = foodRepository.findByStatusAndKeywordAndStoreId(status, keyword, storeId);
        
        // 获取PageHelper分页信息
        Page<Food> pageInfo = (Page<Food>) foods;
        // 转换为VO列表
        List<FoodVO> foodVOs = entity2VO(foods, FoodVO.class);

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), foodVOs);
    }

    /**
     * 审核商品
     */
    @Override
    @Transactional
    public void auditFood(Long foodId, AuditDTO dto) {
        Food food = foodRepository.findById(foodId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.FOOD_NOT_FOUND));

        AuditDTO.AuditStatus status = dto.getStatus();
        if(APPROVED.equals(status)){
            // 只有suspended的商品可以被审核通过(APPROVED)
//            if(!Food.FoodStatus.SUSPENDED.equals(food.getStatus())) {
//                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
//            }

            // 默认状态为下架
            food.setStatus(Food.FoodStatus.OFF_SHELF);
        }else if(SUSPENDED.equals(status)){
            // 不能suspend 已经suspended的商品
            if(Food.FoodStatus.SUSPENDED.equals(food.getStatus())) {
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }

            food.setStatus(Food.FoodStatus.SUSPENDED);
            food.setRejectReason(dto.getReason());
            // todo: 发送通知给商家
        }else{
            // 如果状态不合法，抛出异常
            throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
        }

        food.setUpdatedAt(LocalDateTime.now());
        foodRepository.save(food);
    }

    /**
     * 获取骑手列表
     */
    @Override
    public PageVO<RiderVO> listRiders(Rider.RiderStatus status, String keyword, int page, int size) {
        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);

        // 根据条件查询骑手列表
        List<Rider> riders = riderRepository.findByStatusAndKeyword(status, keyword);

        // 获取PageHelper分页信息
        Page<Rider> pageInfo = (Page<Rider>) riders;
        // 转换为VO列表
        List<RiderVO> riderVOs = entity2VO(riders, RiderVO.class);

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), riderVOs);
    }

    /**
     * 更新骑手状态
     */
    @Override
    @Transactional
    public void updateRiderStatus(Long riderId, AuditDTO dto) {
        Rider rider = riderRepository.findById(riderId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.RIDER_NOT_FOUND));

        AuditDTO.AuditStatus status = dto.getStatus();
        if(APPROVED.equals(status)) {
//            if(!Rider.RiderStatus.SUSPENDED.equals(rider.getStatus())) {
//                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
//            }

            // 默认为离线状态
            rider.setStatus(Rider.RiderStatus.OFFLINE);
        }else if(SUSPENDED.equals(dto.getStatus())) {
            // 不能suspend 已经suspended的骑手
            if(Rider.RiderStatus.SUSPENDED.equals(rider.getStatus())) {
                throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
            }

            rider.setStatus(Rider.RiderStatus.SUSPENDED);
            // todo: set reason
        }else{
            // 如果状态不合法，抛出异常
            throw new CommonException(ExceptionConstant.REQ_PARAM_ERROR);
        }

        rider.setUpdatedAt(LocalDateTime.now());
        riderRepository.save(rider);
    }

    /**
     * 获取所有订单
     */
    @Override
    public PageVO<OrderVO> listAllOrders(Order.OrderStatus status, Long userId, Long storeId, Long riderId, int page, int size) {
        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);

        // 根据条件查询订单列表
        List<Order> orders = orderRepository.findByConditions(status, userId, storeId, riderId);

        // 获取PageHelper分页信息
        Page<Order> pageInfo = (Page<Order>) orders;
        // 转换为VO列表并填充额外信息
        List<OrderVO> orderVOs = orders.stream()
                .map(order -> {
                    OrderVO vo = new OrderVO();
                    BeanUtils.copyProperties(order, vo);

                    // 填充店铺名称等信息
                    storeRepository.findById(order.getStoreId()).ifPresent(store -> {
                        vo.setStoreName(store.getName());
                        vo.setStoreImage(store.getLogo());
                    });

                    return vo;
                })
                .collect(Collectors.toList());

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), orderVOs);
    }

    /**
     * 获取评价列表
     */
    @Override
    public PageVO<ReviewVO> listReviews(Long userId, Long storeId, Long foodId, Integer rating, int page, int size) {
        // 使用PageHelper进行分页
        PageHelper.startPage(page, size);
        
        // 根据条件查询评价列表
        List<Review> reviews = reviewRepository.findByConditionsForAdmin(userId, storeId, foodId, rating);

        // 获取PageHelper分页信息
        Page<Review> pageInfo = (Page<Review>) reviews;
        // 转换为VO列表并填充额外信息
        List<ReviewVO> reviewVOs = reviews.stream()
                .map(review -> {
                    ReviewVO vo = new ReviewVO();
                    BeanUtils.copyProperties(review, vo);

                    // 填充用户信息
                    userRepository.findById(review.getUserId()).ifPresent(user -> {
                        vo.setUserName(user.getUsername());
                        vo.setUserAvatar(user.getAvatar());
                    });

                    // 填充店铺信息
                    storeRepository.findById(review.getStoreId()).ifPresent(store -> {
                        vo.setStoreName(store.getName());
                    });

                    return vo;
                })
                .collect(Collectors.toList());

        // 构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), reviewVOs);
    }

    /**
     * 删除评价
     */
    @Override
    @Transactional
    public void deleteReview(Long reviewId) {
        Review review = reviewRepository.findById(reviewId)
                .orElseThrow(() -> new CommonException(ExceptionConstant.REVIEW_NOT_FOUND));

        // 删除评价
        reviewRepository.delete(review);

        // 更新商家评分
        updateStoreRating(review.getStoreId());
    }

    /**
     * 更新店铺评分 todo: 性能太低
     */
    private void updateStoreRating(Long storeId) {
        List<Review> reviews = reviewRepository.findByStoreId(storeId);
        if (reviews == null || reviews.isEmpty()) {
            return;
        }

        double avgRating = reviews.stream().mapToInt(Review::getStoreRating).average().orElse(0);
        Store store = storeRepository.findById(storeId)
                .orElseThrow(() -> new NotFoundException(ExceptionConstant.STORE_NOT_FOUND));
        
        store.setRating(BigDecimal.valueOf(avgRating)); // 将double转换为BigDecimal
        store.setUpdatedAt(LocalDateTime.now());
        storeRepository.save(store);
    }

    /**
     * 获取平台统计数据
     */
    @Override
    public PlatformStatsVO getPlatformStatistics(LocalDate startDate, LocalDate endDate) {
        // 基础统计数据
        long totalUsers = userRepository.count();
        long totalMerchants = userRepository.countByRole(User.UserRole.MERCHANT);
        long totalRiders = riderRepository.count();
        long totalOrders = orderRepository.count();
        
        // 获取今天的开始和结束时间
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        
        // 今日订单数和交易额
        long todayOrders = orderRepository.countByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, todayStart, todayEnd);
        BigDecimal todayAmount = orderRepository.sumTotalByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, todayStart, todayEnd);
        if (todayAmount == null) {
            todayAmount = BigDecimal.ZERO;
        }
        
        // 本周订单数
        LocalDateTime weekStart = LocalDateTime.of(LocalDate.now().with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY)), LocalTime.MIN);
        long weekOrders = orderRepository.countByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, weekStart, todayEnd);
        
        // 本月订单数
        LocalDateTime monthStart = LocalDateTime.of(LocalDate.now().withDayOfMonth(1), LocalTime.MIN);
        long monthOrders = orderRepository.countByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, monthStart, todayEnd);
        
        // 累计交易额
        BigDecimal totalAmount = orderRepository.sumTotalByStatus(Order.OrderStatus.COMPLETED);
        if (totalAmount == null) {
            totalAmount = BigDecimal.ZERO;
        }

        // 按日期分组统计数据
        Map<String, Long> newUsersData = new LinkedHashMap<>();
        Map<String, Long> orderCountData = new LinkedHashMap<>();
        Map<String, BigDecimal> orderAmountData = new LinkedHashMap<>();
        
        // 计算日期间隔天数
        long daysBetween = ChronoUnit.DAYS.between(startDate, endDate) + 1;
        
        // 如果日期范围超过60天，则按周统计
        boolean groupByWeek = daysBetween > 60;
        
        // 如果日期范围超过365天，则按月统计
        boolean groupByMonth = daysBetween > 365;
        
        // 按天/周/月统计数据
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            String dateKey;
            LocalDate nextDate;
            
            if (groupByMonth) {
                // 按月统计
                dateKey = currentDate.getYear() + "-" + currentDate.getMonthValue();
                nextDate = currentDate.plusMonths(1);
            } else if (groupByWeek) {
                // 按周统计
                dateKey = "W" + currentDate.get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR);
                nextDate = currentDate.plusWeeks(1);
            } else {
                // 按天统计
                dateKey = currentDate.toString();
                nextDate = currentDate.plusDays(1);
            }
            
            LocalDateTime periodStart = LocalDateTime.of(currentDate, LocalTime.MIN);
            LocalDateTime periodEnd;
            
            if (groupByMonth) {
                periodEnd = LocalDateTime.of(currentDate.withDayOfMonth(currentDate.lengthOfMonth()), LocalTime.MAX);
            } else if (groupByWeek) {
                periodEnd = LocalDateTime.of(currentDate.plusDays(6), LocalTime.MAX);
            } else {
                periodEnd = LocalDateTime.of(currentDate, LocalTime.MAX);
            }
            
            // 新增用户数
            long newUsers = userRepository.countByCreatedAtBetween(periodStart, periodEnd);
            newUsersData.put(dateKey, newUsers);
            
            // 订单数量
            long orderCount = orderRepository.countByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, periodStart, periodEnd);
            orderCountData.put(dateKey, orderCount);
            
            // 交易额
            BigDecimal orderAmount = orderRepository.sumTotalByStatusAndCreatedAtBetween(Order.OrderStatus.COMPLETED, periodStart, periodEnd);
            orderAmountData.put(dateKey, orderAmount != null ? orderAmount : BigDecimal.ZERO);
            
            currentDate = nextDate;
        }
        
        // 获取热门商品排行
        List<PlatformStatsVO.TopFoodItemVO> topFoodsData = orderItemRepository.findTopSellingFoods(PageRequest.of(0, 10));
        List<PlatformStatsVO.TopFoodItemVO> topFoods = topFoodsData.stream()
                .map(item -> {
                    Long foodId = item.getFoodId();
                    String foodName = item.getFoodName();
                    String storeName = item.getStoreName();
                    Long salesCount = item.getSalesCount();
                    return new PlatformStatsVO.TopFoodItemVO(foodId, foodName, storeName, salesCount);
                })
                .collect(Collectors.toList());
        
        // 获取热门商家排行
        List<PlatformStatsVO.TopStoreItemVO> topStoresData = orderRepository.findTopStores(PageRequest.of(0, 10));
        List<PlatformStatsVO.TopStoreItemVO> topStores = topStoresData.stream()
                .map(item -> {
                    Long storeId = item.getStoreId();
                    String storeName = item.getStoreName();
                    Long orderCount = item.getOrderCount();
                    BigDecimal salesAmount = item.getSalesAmount();
                    return new PlatformStatsVO.TopStoreItemVO(storeId, storeName, orderCount, salesAmount);
                })
                .collect(Collectors.toList());
        
        // 构建并返回统计数据
        return PlatformStatsVO.builder()
                .totalUsers(totalUsers)
                .totalMerchants(totalMerchants)
                .totalRiders(totalRiders)
                .totalOrders(totalOrders)
                .totalAmount(totalAmount)
                .todayOrders(todayOrders)
                .todayAmount(todayAmount)
                .weekOrders(weekOrders)
                .monthOrders(monthOrders)
                .newUsersData(newUsersData)
                .orderCountData(orderCountData)
                .orderAmountData(orderAmountData)
                .topFoods(topFoods)
                .topStores(topStores)
                .build();
    }

    @Override
    public PageVO<StoreCategoryVO> listStoreCategory(int page, int size) {
        //使用PageHelper进行分页
        PageHelper.startPage(page, size);
        //查询店铺种类
        List<StoreCategory> storeCategories = storeCategoryRepository.findAll();
        //获取PageHelper分页信息
        Page<StoreCategory> pageInfo = (Page<StoreCategory>) storeCategories;
        //转换为VO列表
        List<StoreCategoryVO> storeCategoryVOs = entity2VO(storeCategories, StoreCategoryVO.class);

        //构造分页结果
        return new PageVO<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), storeCategoryVOs);
    }

    @Override
    public StoreCategoryVO addStoreCategory(StoreCategoryDTO dto) {
        StoreCategory  category = new StoreCategory();
        BeanUtils.copyProperties(dto, category);
        category.setCreatedAt(LocalDateTime.now());
        storeCategoryRepository.insert(category);
        return entity2VO(category, StoreCategoryVO.class);
    }

    @Override
    public StoreCategoryVO updateStoreCategory(Long id, StoreCategoryDTO dto) {
        StoreCategory category = storeCategoryRepository.findById(id);
        if (category == null) {
            throw new NotFoundException(ExceptionConstant.STORE_CATEGORY_NOT_FOUND);
        }
        BeanUtils.copyProperties(dto, category);
        category.setCreatedAt(LocalDateTime.now());
        storeCategoryRepository.update(category);
        return entity2VO(category, StoreCategoryVO.class);
    }

    @Override
    public void deleteStoreCategory(Long id) {
        StoreCategory category = storeCategoryRepository.findById(id);
        if (category == null) {
            throw new NotFoundException(ExceptionConstant.STORE_CATEGORY_NOT_FOUND);
        }
        storeCategoryRepository.deleteById(id);
    }

    @Override
    public OrderDetailVO getOrderDetail(Long id) {
        return orderService.getOrderDetail(id);
    }
}